package com.starmark.core.framework.advice;

import com.starmark.core.framework.exception.BaseException;
import com.starmark.core.framework.response.ErrorResponseData;
import com.starmark.core.framework.response.HttpCode;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;


/**
 * 处理业务逻辑时可能会发生各种问题，如数据库报错、请求参数格式错误/缺失/值非法等。此类异常的捕获方法有两种，对于提供RESTful服务的应用，
 * 使用@ControllerAdvice和@ExceptionHandler注解;
 * 对于使用模板渲染HTML的应用，实现HandlerExceptionResolver接口。
 * <p>
 * 先说说RESTful应用，由于返回的是JSON而不是页面，因此在异常处理方法中就不能返回ModelAndView对象
 * http://blog.csdn.net/neosmith/article/details/51090509
 */
@Order(-1)
@ControllerAdvice
public class ExceptionHandlerAdvice {
    protected final Logger logger = LoggerFactory.getLogger(
            ExceptionHandlerAdvice.class);


    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ErrorResponseData handleBadRequest(HttpServletRequest request, Exception ex) throws Exception {
        logger.error("系统内部错误,请联系管理员", ex);
        if(request.getHeader("feign-header")!=null){
            throw ex;
        }
        ErrorResponseData data = new ErrorResponseData();
        data.setCode(HttpCode.INTERNAL_SERVER_ERROR.code());
        data.setMsg(ex.getMessage());


        data.setStackMsg(ExceptionUtils.getStackTrace(ex));
        return data;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorResponseData handle404(HttpServletRequest request,NoHandlerFoundException e) throws NoHandlerFoundException {
        if(request.getHeader("feign-header")!=null){
            throw e;
        }
        logger.info("Resource Not found, RequestURL: {}, HttpMethod: {}, Headers: {}", e.getRequestURL(),
                e.getHttpMethod(), e.getHeaders());
        logger.error(e.getMessage(), e);
        ErrorResponseData data = new ErrorResponseData();
        data.setCode(HttpCode.NOT_FOUND.code());
        data.setMsg(e.getMessage());
        data.setStackMsg(ExceptionUtils.getStackTrace(e));
        return data;
    }

    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    public ErrorResponseData handleAll(HttpServletRequest request,MultipartException t){
        if(request.getHeader("feign-header")!=null){
            throw t;
        }
        logger.error("文件上传超出大小", t);
        return ErrorResponseData.newInstance(HttpCode.ENTITY_TOO_LARGE, "文件超过指定大小");
    }



    @ExceptionHandler(BaseException.class)
    @ResponseBody
    public ErrorResponseData handleBaseException(HttpServletRequest request, BaseException ex) {
        logger.error("系统内部错误,请联系管理员", ex);
        if(request.getHeader("feign-header")!=null){
            throw ex;
        }
        ErrorResponseData data = new ErrorResponseData();
        data.setCode(ex.getCode().code());
        data.setMsg(ex.getCode().msg());
        data.setStackMsg(ExceptionUtils.getStackTrace(ex));
        return data;
    }
}
